package com.zkzx.company.api.config.resource;

import com.zkzx.company.api.mapper.CompanyAuthorityMapper;
import com.zkzx.company.api.mapper.entity.CompanyAuthority;
import com.zkzx.company.api.mapper.entity.CompanyRoleAuthority;
import com.zkzx.company.api.mapper.entity.MemberRole;
import com.zkzx.company.api.service.authorization.MemberRoleService;
import com.zkzx.company.api.service.authorization.CompanyRoleAuthorityService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * MyInvocationSecurityMetadataSourceService
 * Created by young on 2021/4/26.
 */
@Slf4j
@Service
public class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource {

    @Autowired
    MemberRoleService memberRoleService;

    @Autowired
    CompanyRoleAuthorityService companyRoleAuthorityService;

    @Resource
    CompanyAuthorityMapper authorityMapper;

    // 菜单栏 不单独给每个用户进行配置 token验证通过 菜单不用鉴权
    private final static String MENUS = "/menus";

    /*
    * 此方法判断用户请求的url，是否跟上述的map的key值匹配，如果匹配，则把该url所需要的权限（value值）传给MyAccessDecisionManager.decide方法进行下一步判断
    * 如果不匹配，则看是要return null 放行，还是直接抛出AccessDeniedException异常报没有权限（即默认白名单还是黑名单的问题）
    * */
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {

        // object 中包含用户请求的request 信息
        HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();

        log.info("当前请求路径：{}",request.getServletPath());

        String userId = request.getHeader("userId");

        if(Objects.isNull(userId)){
            throw new AccessDeniedException("当前用户没有登录");
        }

        // 获取用户管理的角色
        MemberRole userRole = memberRoleService.getByMemberId(Integer.parseInt(userId));

        ConfigAttribute cfg = new SecurityConfig(userRole.getRoleid().toString());

        // token验证通过 菜单不用鉴权
        AntPathRequestMatcher matcher = new AntPathRequestMatcher(MENUS);
        if (matcher.matches(request)){
            return  new ArrayList<ConfigAttribute>() {{
                add(cfg);
            }};
        }
        if(Objects.isNull(userRole)){
            throw new AccessDeniedException("没有权限");
        }

        // 封装用户的权限信息
        List<CompanyRoleAuthority> roleAuthorities = companyRoleAuthorityService.getByRoleId(userRole.getRoleid());
        if(CollectionUtils.isEmpty(roleAuthorities)){
            throw new AccessDeniedException("没有权限");
        }

        for (CompanyRoleAuthority roleAuthority : roleAuthorities) {
            CompanyAuthority authority = authorityMapper.selectByPrimaryKey(roleAuthority.getAuthorityid());

            matcher = new AntPathRequestMatcher(authority.getPath());
            // 地址相同 请求方法也匹配
            if (matcher.matches(request) && request.getMethod().equals(authority.getMethod())) {
                return  new ArrayList<ConfigAttribute>() {{
                    add(cfg);
                }};
            }
        }

        //默认黑名单
        throw new AccessDeniedException("没有权限");
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
